package com.flyan.game.motafx.component.character;

import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.dsl.components.EffectComponent;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxgl.physics.BoundingShape;
import com.almasb.fxgl.physics.HitBox;
import com.almasb.fxgl.texture.AnimatedTexture;
import com.almasb.fxgl.time.TimerAction;
import com.flyan.game.motafx.component.BattleComponent;
import com.flyan.game.motafx.component.EquipSlotsComponent;
import com.flyan.game.motafx.config.GameConfig;
import com.flyan.game.motafx.core.algorithm.BraveMoveAlgorithm;
import com.flyan.game.motafx.core.enums.DirEnum;
import com.flyan.game.motafx.core.event.enums.EventListenerTypeEnum;
import com.flyan.game.motafx.core.map.FloorMap;
import com.flyan.game.motafx.core.util.animate.WalkingCharacterAnimate;
import com.flyan.game.motafx.core.util.core.GameUtils;
import com.flyan.game.motafx.effect.terrain.StairEffect;
import javafx.geometry.Point2D;
import javafx.util.Duration;

/**
 * 勇士组件
 *
 * @author flyan
 * @version 1.0
 * @email flyan_by_chenu@sina.com
 * @since 2025/1/31
 */
public class BraveComponent extends Component {

    /**
     * 移动速度，一秒几个格子
     */
    private static final int MOVE_SPEED = GameConfig.GRID_SIZE * 5;

    private final EquipSlotsComponent equipSlotsComponent;
    private final BattleComponent battleComponent;
    private final EffectComponent effectComponent;

    private AnimatedTexture atView;

    /**
     * 行走动画
     */
    private WalkingCharacterAnimate walkAnimate;
    private boolean lastMovingStatus; // 最后一次检测的移动状态
    private boolean moving;
    private Point2D moveTo;
    private DirEnum dir;

    private TimerAction movingStatusCheckTimer;

    /**
     * 当前所在楼层地图
     */
    private FloorMap floor;

    /**
     * 勇士移动算法
     */
    private BraveMoveAlgorithm moveAlgorithm;

    public BraveComponent() {
        equipSlotsComponent = new EquipSlotsComponent();
        battleComponent = new BattleComponent();
        effectComponent = new EffectComponent();
        moveAlgorithm = new BraveMoveAlgorithm();
        walkAnimate = WalkingCharacterAnimate.builder()
                .image("images/brave.png")
                .duration(Duration.seconds(0.75))
                .frame(4, GameConfig.GRID_SIZE, GameConfig.GRID_SIZE)
                .up(12, 15)
                .down(0, 3)
                .left(4, 7)
                .right(8, 11)
                .build();
        /* 初始时向下 */
        dir = DirEnum.DOWN;
        atView = new AnimatedTexture(walkAnimate.getDown());
    }

    @Override
    public void onAdded() {
        entity.addComponent(equipSlotsComponent); // 装备槽
        entity.addComponent(battleComponent); // 战斗组件
        entity.addComponent(effectComponent); // 效果组件

        entity.getViewComponent().addChild(atView);
        entity.getBoundingBoxComponent().addHitBox(new HitBox(BoundingShape.box(
                GameConfig.GRID_BBOX_SIZE,
                GameConfig.GRID_BBOX_SIZE)));

        /* 每 0.1s 持续检查移动状态，若是最后一次和当前都是停止，停止移动动画 */
        movingStatusCheckTimer = FXGL.run(() -> {
            if (!moving && !lastMovingStatus) {
                atView.stop();
            }
            lastMovingStatus = moving;
        }, Duration.seconds(0.1));
    }

    @Override
    public void onRemoved() {
        movingStatusCheckTimer.expire();
    }

    @Override
    public void onUpdate(double tpf) {
        if (moving) {
            Point2D position = entity.getPosition();
            double maxDistance = GameConfig.GRID_SIZE;
            switch (dir) {
                case UP, DOWN -> {
                    maxDistance = Math.abs(moveTo.getY() - position.getY());
                }
                case LEFT, RIGHT -> {
                    maxDistance = Math.abs(moveTo.getX() - position.getX());
                }
            }
            double distance = Math.min(MOVE_SPEED * tpf, maxDistance); // 当前帧需要移动的距离

            double dx = dir.getVector().getX() * distance;
            double dy = dir.getVector().getY() * distance;
            Point2D targetPos = position.add(dx, dy);
            entity.translate(dx, dy);
            if (targetPos.getX() == moveTo.getX() && targetPos.getY() == moveTo.getY()) {
                /* 勇士位置改变，尝试触发移动到目标位置事件 */
                GameUtils.app().eventService.typeOccur(EventListenerTypeEnum.MOVE_TO_TARGET);
                moving = false;
            }
        }
    }

    public void setFloor(FloorMap floor) {
        this.floor = floor;
        if (floor != null) {
            moveAlgorithm.setFloor(floor);
        }
    }

    public FloorMap getFloor() {
        return floor;
    }

    /**
     * 移动
     *
     * @param dir 方向
     * @return 是否移动成功
     */
    public boolean move(DirEnum dir) {
        /* 当前正在移动 */
        if (moving) {
            return false;
        }

        /* 当前正在战斗 */
        if (battleComponent.isAttacking()) {
            return false;
        }

        /* 切换转身动画 */
        switch (dir) {
            case UP -> {
                if (atView.getAnimationChannel() != walkAnimate.getUp()) {
                    atView.playAnimationChannel(walkAnimate.getUp());
                }
            }
            case DOWN -> {
                if (atView.getAnimationChannel() != walkAnimate.getDown()) {
                    atView.playAnimationChannel(walkAnimate.getDown());
                }
            }
            case LEFT -> {
                if (atView.getAnimationChannel() != walkAnimate.getLeft()) {
                    atView.playAnimationChannel(walkAnimate.getLeft());
                }
            }
            case RIGHT -> {
                if (atView.getAnimationChannel() != walkAnimate.getRight()) {
                    atView.playAnimationChannel(walkAnimate.getRight());
                }
            }
        }

        /* 检查是否可移动 */
        if (!moveAlgorithm.moveOneStep(dir)) {
            return false;
        }

        /* 移动开始 */
        onMoveStart(dir);

        return true;
    }

    private void onMoveStart(DirEnum dir) {
        moving = true;
        /* 播放行走动画 */
        if (!lastMovingStatus) {
            atView.loop();
        }

        /* 移动开始，解除楼梯的上下楼效果 */
        if (effectComponent.hasEffect(StairEffect.class)) {
            effectComponent.endEffect(StairEffect.class);
        }

        /* 设置移动方向和目标位置 */
        this.dir = dir;
        Point2D position = entity.getPosition();
        moveTo = position.add(dir.getVector().getX() * GameConfig.GRID_SIZE, dir.getVector().getY() * GameConfig.GRID_SIZE);
    }

    /**
     * 停止移动
     */
    public void stopMove() {

    }

    /**
     * 传送到指定位置
     *
     * @param position 位置
     */
    public void teleport(Point2D position) {
        moving = false;
        moveTo = position;
        entity.setPosition(position);
    }

}
